package com.alston.rest.common;


import java.io.UnsupportedEncodingException;
import java.util.Date;

import com.alston.rest.common.bean.RedisKeyConstant;
import com.alston.rest.common.utils.DateUtils;
import com.alston.rest.common.utils.StringUtils;
import com.alston.rest.model.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;


/** 
* @ClassName: TokenManager 
* @Description: Token管理，使用redis缓存
* @author alston 
* @date 2018年5月23日 下午9:11:24 
*  
*/
public class TokenManager {
	
	private static int JWT_EXPIRE_MIN = Integer.parseInt(PropKit.get("JWT_EXPIRE_MIN")); //JWT秘钥
	private static String JWT_SECRET = PropKit.get("JWT_SECRET");//JWT失效时间 单位：分钟
	//private static Logger log = Logger.getLogger("TokenManager");
    /**
     * 生成jwt token
     * @param userId 
     * @param expireTime 过期时间戳
     * @return
     */
    public static String createJwtToken(String userId){
        long nowMillis = System.currentTimeMillis();
        Date now=new Date(nowMillis);//签发时间精度:毫秒
        Date expireTime = DateUtils.getAfterMinDate(JWT_EXPIRE_MIN);
        
        try {
            Algorithm algorithm = Algorithm.HMAC256(JWT_SECRET);
            return JWT.create().withIssuer(userId).withIssuedAt(now).withExpiresAt(expireTime).sign(algorithm);
        } catch (UnsupportedEncodingException exception){
            exception.printStackTrace();
        } catch (JWTCreationException exception){
            exception.printStackTrace();
        }
        return null;
    }
    
    
    public static Cache mainCache = Redis.use("main");
    
    /**
     * 验证token
     * @param token
     * @return
     */
    public static User getUser(String token) {
    	return mainCache.get(RedisKeyConstant.FIND_USER_BY_TOKEN+token); 
    }

    /**
     * 生成token信息
     * @param user
     * @return
     */
    public static String generateTokenInfo(String token,User user) {
        Long userId = user.getLong("userId");
        String oldToken = mainCache.get(RedisKeyConstant.FIND_TOKEN_BY_USER_ID+userId);
        if(StringUtils.isNotEmpty(oldToken)) {
        	mainCache.del(RedisKeyConstant.FIND_TOKEN_BY_USER_ID+userId);
        	mainCache.del(RedisKeyConstant.FIND_USER_BY_TOKEN+oldToken); 
        }
        
        mainCache.set(RedisKeyConstant.FIND_TOKEN_BY_USER_ID+userId,token);
    	mainCache.set(RedisKeyConstant.FIND_USER_BY_TOKEN+token,user);
    	
//    	mainCache.expire(RedisKeyConstant.FIND_TOKEN_BY_USER_ID+userId, 60000);
//    	mainCache.expire(RedisKeyConstant.FIND_USER_BY_TOKEN+token, 60000);
    	
        return token;
    }
    
    
    /**
     * 校验toekn是否有效
     * @param userId
     * @param token
     * @return
     */
    public static boolean validateToken(String userId,String token){
        boolean active = true;
        try {
            Algorithm algorithm = Algorithm.HMAC256(JWT_SECRET);//声明签名所用的算法和秘钥
            JWTVerifier verifier = JWT.require(algorithm).withIssuer(userId).build();
            verifier.verify(token);
        } catch (TokenExpiredException exception){
            //System.out.println("--- token 过期");
            active = false;
        } catch (JWTDecodeException exception){
            //System.out.println("--- token 无效");
            active = false;
        } catch (UnsupportedEncodingException exception){
            //System.out.println("--- token 无效");
            active = false;
        } catch (JWTVerificationException exception){
            //System.out.println("--- token 错误");
            active = false;
        }
        return active;
    }
    
    /**移除相关用户token和信息
     * @param userId
     * @param token
     */
    public void removeToken(String userId,String token){
    	mainCache.del(RedisKeyConstant.FIND_TOKEN_BY_USER_ID+userId);
    	mainCache.del(RedisKeyConstant.FIND_USER_BY_TOKEN+token); 
    }
      
}
